import random
import time
import threading
from typing import List, Dict, Any, Optional
from fake_useragent import UserAgent
import logging

logger = logging.getLogger(__name__)

class AntiDetection:
    def __init__(self, config=None):
        self.config = config
        self.ua = UserAgent()
        
        # User-Agent池
        self.user_agents = [
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36',
            'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
            'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36',
            'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:120.0) Gecko/20100101 Firefox/120.0',
            'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:120.0) Gecko/20100101 Firefox/120.0',
            'Mozilla/5.0 (X11; Linux x86_64; rv:120.0) Gecko/20100101 Firefox/120.0',
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Edge/120.0.0.0',
            'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Safari/605.1.15'
        ]
        
        # 常见浏览器头部
        self.common_headers = {
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
            'Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7',
            'Accept-Encoding': 'gzip, deflate, br',
            'DNT': '1',
            'Connection': 'keep-alive',
            'Upgrade-Insecure-Requests': '1',
            'Sec-Fetch-Dest': 'document',
            'Sec-Fetch-Mode': 'navigate',
            'Sec-Fetch-Site': 'none',
            'Sec-Fetch-User': '?1',
            'Cache-Control': 'max-age=0',
        }
        
        # 延时配置
        self.delay_config = {
            'min_delay': 1,
            'max_delay': 5,
            'request_count': 0,
            'last_request_time': 0,
            'adaptive_delay': True
        }
        
        # 请求频率限制
        self.rate_limiter = RateLimiter()
        
    def get_random_user_agent(self, browser: Optional[str] = None) -> str:
        """获取随机User-Agent"""
        try:
            if browser:
                return self.ua.get_browser(browser)
            else:
                return random.choice(self.user_agents)
        except Exception:
            return random.choice(self.user_agents)
    
    def get_random_headers(self, referer: Optional[str] = None, custom_headers: Optional[Dict] = None) -> Dict[str, str]:
        """获取随机请求头"""
        headers = self.common_headers.copy()
        headers['User-Agent'] = self.get_random_user_agent()
        
        # 添加随机Accept-Language
        languages = [
            'en-US,en;q=0.9',
            'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7',
            'zh-CN,zh;q=0.9,en;q=0.8',
            'en-GB,en;q=0.9',
            'fr-FR,fr;q=0.9,en;q=0.8',
            'de-DE,de;q=0.9,en;q=0.8'
        ]
        headers['Accept-Language'] = random.choice(languages)
        
        # 添加Referer
        if referer:
            headers['Referer'] = referer
        
        # 随机添加一些可选头部
        optional_headers = {
            'Sec-CH-UA': '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
            'Sec-CH-UA-Mobile': '?0',
            'Sec-CH-UA-Platform': random.choice(['"Windows"', '"macOS"', '"Linux"'])
        }
        
        for key, value in optional_headers.items():
            if random.random() > 0.3:  # 70%概率添加
                headers[key] = value
        
        # 合并自定义头部
        if custom_headers:
            headers.update(custom_headers)
        
        return headers
    
    def adaptive_delay(self, response_time: Optional[float] = None, status_code: Optional[int] = None):
        """自适应延时"""
        self.delay_config['request_count'] += 1
        current_time = time.time()
        
        # 基础延时
        base_delay = random.uniform(self.delay_config['min_delay'], self.delay_config['max_delay'])
        
        if self.delay_config['adaptive_delay']:
            # 根据响应时间调整延时
            if response_time:
                if response_time > 3:  # 响应慢，增加延时
                    base_delay *= 1.5
                elif response_time < 0.5:  # 响应快，稍微减少延时
                    base_delay *= 0.8
            
            # 根据状态码调整延时
            if status_code:
                if status_code == 429:  # 限流
                    base_delay *= 3
                    logger.warning("Received 429, increasing delay")
                elif status_code >= 500:  # 服务器错误
                    base_delay *= 1.5
            
            # 根据请求频率调整延时
            if self.delay_config['last_request_time'] > 0:
                time_since_last = current_time - self.delay_config['last_request_time']
                if time_since_last < 1:  # 请求太频繁
                    base_delay *= 1.2
        
        self.delay_config['last_request_time'] = current_time
        
        logger.debug(f"Adaptive delay: {base_delay:.2f}s")
        time.sleep(base_delay)
    
    def simulate_human_behavior(self):
        """模拟人类行为"""
        behaviors = [
            self._random_mouse_movement,
            self._random_scroll,
            self._random_click,
            self._random_typing_delay
        ]
        
        # 随机执行一些行为
        for _ in range(random.randint(1, 3)):
            behavior = random.choice(behaviors)
            behavior()
    
    def _random_mouse_movement(self):
        """模拟随机鼠标移动"""
        time.sleep(random.uniform(0.1, 0.5))
        logger.debug("Simulated mouse movement")
    
    def _random_scroll(self):
        """模拟随机滚动"""
        time.sleep(random.uniform(0.2, 1.0))
        logger.debug("Simulated scrolling")
    
    def _random_click(self):
        """模拟随机点击"""
        time.sleep(random.uniform(0.1, 0.3))
        logger.debug("Simulated clicking")
    
    def _random_typing_delay(self):
        """模拟打字延时"""
        time.sleep(random.uniform(0.05, 0.2))
        logger.debug("Simulated typing delay")
    
    def rotate_session_data(self, session):
        """轮换会话数据"""
        # 清除cookies
        if hasattr(session, 'cookies'):
            session.cookies.clear()
        
        # 更新User-Agent
        if hasattr(session, 'headers'):
            session.headers.update({'User-Agent': self.get_random_user_agent()})
        
        logger.debug("Session data rotated")
    
    def check_detection_signals(self, response_text: str, status_code: int) -> Dict[str, Any]:
        """检查反爬虫检测信号"""
        detection_signals = {
            'captcha_detected': False,
            'rate_limited': False,
            'blocked': False,
            'suspicious_content': False,
            'recommendations': []
        }
        
        # 检查验证码
        captcha_keywords = ['captcha', 'verify', 'robot', 'human', 'challenge', '验证码', '人机验证']
        if any(keyword in response_text.lower() for keyword in captcha_keywords):
            detection_signals['captcha_detected'] = True
            detection_signals['recommendations'].append('Switch proxy or increase delay')
        
        # 检查限流
        if status_code == 429:
            detection_signals['rate_limited'] = True
            detection_signals['recommendations'].append('Increase request delay significantly')
        
        # 检查封禁
        if status_code in [403, 503] or 'blocked' in response_text.lower():
            detection_signals['blocked'] = True
            detection_signals['recommendations'].append('Change IP address and User-Agent')
        
        # 检查可疑内容
        suspicious_keywords = ['access denied', 'permission denied', 'unauthorized', 'forbidden']
        if any(keyword in response_text.lower() for keyword in suspicious_keywords):
            detection_signals['suspicious_content'] = True
            detection_signals['recommendations'].append('Review request headers and cookies')
        
        return detection_signals
    
    def get_stealth_config(self) -> Dict[str, Any]:
        """获取隐匿配置"""
        return {
            'headers': self.get_random_headers(),
            'delay_range': [self.delay_config['min_delay'], self.delay_config['max_delay']],
            'timeout': random.randint(10, 30),
            'max_retries': random.randint(2, 4)
        }

class RateLimiter:
    """请求频率限制器"""
    
    def __init__(self, max_requests: int = 10, time_window: int = 60):
        self.max_requests = max_requests
        self.time_window = time_window
        self.requests = []
        self.lock = threading.Lock()
    
    def acquire(self) -> bool:
        """获取请求许可"""
        with self.lock:
            current_time = time.time()
            
            # 移除过期的请求记录
            self.requests = [req_time for req_time in self.requests 
                           if current_time - req_time < self.time_window]
            
            # 检查是否超过限制
            if len(self.requests) >= self.max_requests:
                # 计算需要等待的时间
                wait_time = self.time_window - (current_time - self.requests[0])
                if wait_time > 0:
                    logger.info(f"Rate limit reached, waiting {wait_time:.2f}s")
                    time.sleep(wait_time)
                    return self.acquire()  # 递归重试
            
            # 记录当前请求
            self.requests.append(current_time)
            return True

class SessionManager:
    """会话管理器"""
    
    def __init__(self, max_sessions: int = 5):
        self.max_sessions = max_sessions
        self.sessions = []
        self.current_session_index = 0
        self.lock = threading.Lock()
    
    def get_session(self):
        """获取可用会话"""
        with self.lock:
            if not self.sessions:
                return None
            
            session = self.sessions[self.current_session_index]
            self.current_session_index = (self.current_session_index + 1) % len(self.sessions)
            return session
    
    def add_session(self, session):
        """添加会话"""
        with self.lock:
            if len(self.sessions) < self.max_sessions:
                self.sessions.append(session)
            else:
                # 替换最旧的会话
                self.sessions[self.current_session_index] = session
    
    def rotate_sessions(self, anti_detection: AntiDetection):
        """轮换所有会话"""
        with self.lock:
            for session in self.sessions:
                anti_detection.rotate_session_data(session)
            logger.info(f"Rotated {len(self.sessions)} sessions")